#include <iostream>
#include <functional>
#include "include/muduo/net/TcpClient.h"
#include "include/muduo/net/EventLoopThread.h"
#include "include/muduo/base/CountDownLatch.h"

class TranslateClient
{
public:
    TranslateClient(const std::string& sip, int sport)
    : _client(_elp.startLoop(), {sip, sport}, "translate_client")
    , _latch(1)
    {
        _client.setConnectionCallback(std::bind(&TranslateClient::onConnection, this, std::placeholders::_1));
        _client.setMessageCallback(std::bind(&TranslateClient::onMessage, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
    }

    void send(const std::string& str)
    {
        _conn->send(str);
    }
    
    void connect()
    {
        _client.connect();
        _latch.wait();
    }

    ~TranslateClient()
    {}

private:
    void onConnection(const muduo::net::TcpConnectionPtr &conn)
    {
        // 连接建立成功/断开连接时被调用的函数
        if (conn->connected())
        {
            //获取客⼾端对应的通信连接Connection对象的接⼝，发起connect后，有可能还没有连接建⽴成功,因为连接建立成功与建立连接是异步的
            // 则就会导致外部用户在输入发送消息时，连接依然没有建立成功，所以我们需要在连接建立成功之后才能真正开始进行后续的发送消息
            // 所以我们需要将连接服务器与获取服务器连接对象这两个过程设置成为同步的，这时候就需要CountDownLatch
            _conn = _client.connection();
            _latch.countDown();
            std::cout << "连接建立成功" << std::endl;
        }
        else if (conn->disconnected())
        {
            std::cout << "断开连接" << std::endl;
        }
    }

    void onMessage(const muduo::net::TcpConnectionPtr &conn, muduo::net::Buffer *buffer, muduo::Timestamp)
    {
        // 消息到来时被调用的函数
        std::cout << buffer->retrieveAllAsString() << std::endl;
    }

private:
    // 因为EventLoop是一个死循环阻塞事件，而对于客户端除了接收消息之外还要接收用户处理的消息与服务器不同，这两个工作是异步的
    // 而服务器中连接到来或者消息到和后续的处理方式是同步的，所以让Loop阻塞的死循环是对的
    // 所以我们要让客户端的事件监控与用户的输入是两个执行流，这样的话，才可以保证客户端的正常进行，所以我们需要使用ThreadEventLoop
    // EventLoopThread类在实例化的时候就自行开始了事件监听的循环
    muduo::net::EventLoopThread _elp;

    muduo::net::TcpClient _client;

    // 持久化连接服务器的对象类，不需要重复获取
    muduo::net::TcpConnectionPtr _conn;

    // 
    muduo::CountDownLatch _latch;

};


int main()
{
    TranslateClient tc("127.0.0.1", 8080);
    tc.connect();

    while(1)
    {
        std::string buffer;
        std::cin >> buffer;
        tc.send(buffer);
    }
    return 0;
}